#include "ValueEncodedSolution2d.h"
#include "../../../Exception/GA_Exception.h"

template <typename T>
ValueEncodedSolution2d<T>::ValueEncodedSolution2d()
{
}
template <typename T>
ValueEncodedSolution2d<T>::ValueEncodedSolution2d(vector<vector<T> > sol)
{
    solution = sol;
}

template <typename T>
ValueEncodedSolution2d<T>::~ValueEncodedSolution2d()
{
}

template <typename T>
Solution *ValueEncodedSolution2d<T>::clone()
{
    ValueEncodedSolution2d<T> *ves2d = new ValueEncodedSolution2d<T>(solution);
    ves2d->setFitness(fitness);
    return ves2d;
}

template <typename T>
ostream &ValueEncodedSolution2d<T>::outputSolution(ostream &output)
{
    unsigned int size = solution.size();
    for (unsigned int i = 0; i < size; ++i)
    {
        unsigned int size2 = solution[i].size();
        for (unsigned int j = 0; j < size2; ++j)
        {
            output << solution[i][j] << ' ';
        }
        output << "\n";
    }
    return output;
}

template <typename T>
void ValueEncodedSolution2d<T>::push(unsigned int row, T value)
{
    if (row > solution.size())
        throw Invalid_index_exception();
    
    solution[row].push_back(value);
}

template <typename T>
void ValueEncodedSolution2d<T>::push(vector<T> newRow)
{
    solution.push_back(newRow);
}

template <typename T>
T ValueEncodedSolution2d<T>::pop(unsigned int row)
{
    if (row > solution.size())
        throw Invalid_index_exception();
    
    T value = solution[row].back();
    solution[row].pop_back();
    return value;
}

template <typename T>
vector<T> ValueEncodedSolution2d<T>::pop()
{
    vector<T> row = solution.back();
    solution.pop_back();
    return row;
}

void ValueEncodedSolution2d<bool>::mutate()
{
    for (unsigned int i = 0; i < solution.size(); ++i) 
	{
        for (unsigned int j = 0; j < solution[i].size(); ++j)
        {
	        if ((MyRandom::randDbl() * 1000000) < (mutationRate * 1000000)) 
	        {
	            solution[i][j] = !solution[i][j]; 
	        }
        }
    }
}

template <typename T>
void ValueEncodedSolution2d<T>::mutate()
{
}

template <typename T>
void ValueEncodedSolution2d<T>::setValue(unsigned int row, unsigned int column, T value)
{
    if (row > solution.size())
        throw Invalid_index_exception();
    
    if (column > solution[row].size())
        throw Invalid_index_exception();
    
    solution[row][column] = value;
}

template <typename T>
T ValueEncodedSolution2d<T>::getValue(unsigned int row, unsigned int column)
{
    if (row > solution.size())
        throw Invalid_index_exception();
    
    if (column > solution[row].size())
        throw Invalid_index_exception();
        
    return solution[row][column];
}

template <typename T>
unsigned int ValueEncodedSolution2d<T>::getRowCount()
{
    return solution.size();
}

template <typename T>
unsigned int ValueEncodedSolution2d<T>::getColumnCount(unsigned int row)
{
    if (row >= solution.size())
        throw Invalid_index_exception();
        
    return solution[row].size();
}

template <typename T>
vector<vector<T> > ValueEncodedSolution2d<T>::getSolution()
{
    return solution;
}

template class ValueEncodedSolution2d<bool>;
template class ValueEncodedSolution2d<int>;
template class ValueEncodedSolution2d<unsigned int>;
template class ValueEncodedSolution2d<float>;
template class ValueEncodedSolution2d<double>;
template class ValueEncodedSolution2d<long>;
template class ValueEncodedSolution2d<char>;
